#include "server.h"

Server::Server()
{
    m_nextMsgSize = 0;
    // Сервер прослушивает входящие соединения с любого адреса с порта 2323
    if(this->listen(QHostAddress::Any, 2323)){
        qDebug() << "Listening...";
    } else {
        qDebug() << "Error" << errorString();

    }

    // вариант из qt-документации
        QString ipAddress;
        const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
        // используем первый non-localhost IPv4 адрес
        for (const QHostAddress &entry : ipAddressesList) {
            if (entry != QHostAddress::LocalHost && entry.toIPv4Address()) {
                ipAddress = entry.toString();
                break;
            }
        }
        // если не найдено ни одного адреса, используем IPv4 localhost
        if (ipAddress.isEmpty())
            ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
        qDebug() << tr("The server is running on IP: %1 port: %2")
                             .arg(ipAddress).arg(serverPort());

    // почему цепляется клиент, если у него подключение к адресу 127.0.0.1??? а у сервера другой адрес
}

Server::~Server()
{
    close();
}

void Server::sendToClient(QString message)
{
    m_data.clear();
    QDataStream out(&m_data, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_12);

    out << quint16(0) << message;
    out.device()->seek(0);
    out << quint16(m_data.size() - sizeof(quint16));

    qDebug() << "m_sockets.size()" << m_sockets.size();
    QList<QTcpSocket *>::const_iterator it = m_sockets.begin();
    while(it !=m_sockets.end()){
        (*it)->write(m_data);
        ++it;
    }
    //m_socket->write(m_data);   // данные отправлены
    qDebug() << "write message";

}

void Server::incomingConnection(qintptr socketDescriptor)
{
    QTcpSocket *socket = new QTcpSocket();
    socket->setSocketDescriptor(socketDescriptor);
    connect(socket, &QTcpSocket::readyRead, this, &Server::slotReadyRead);
    // при отключении клиента удалится сокет сразу как это станет возможным
    connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
    connect(socket, &QTcpSocket::disconnected, this, &Server::slotDisconnectSocket);

    qDebug() << "Server::incomingConnection() m_socket" << socket;
    m_sockets.append(socket);
    qDebug() << "client connect" << socketDescriptor;

}

void Server::slotReadyRead()
{
    QTcpSocket *socket = (QTcpSocket*)(sender());

    //m_socket = qobject_cast<QTcpSocket*>(sender()); // с какого сокета пришел запрос
    QDataStream in(socket);
    in.setVersion(QDataStream::Qt_5_12);
    qDebug() << "Server::slotReadyRead() m_socket" << socket << in.status();
    if(in.status() == QDataStream::Ok)
    {
        qDebug()<< "ready...";
        qDebug() << "m_nextMsgSize" << m_nextMsgSize;
        for(;;){
            if(m_nextMsgSize == 0){ // сообщение пришло с ошибкой
                // для чтения доступно не меньше 2 байт
                if(socket->bytesAvailable() < 2){
                    qDebug() << "Data < 2 => break";
                    break;
                }
                in >> m_nextMsgSize;
                qDebug() << "m_nextMsgSize = " << m_nextMsgSize;
            }

            if(socket->bytesAvailable() < m_nextMsgSize){
                qDebug() << "Data not full => break";
                break;
            }
            // сообщение пришло полностью
            QString str;
            in >> str;
            m_nextMsgSize = 0;
            qDebug() << str;
            sendToClient(str);
            break;

        } // end to for(;;)

    } else {
        qDebug()<< "error to connect read socket";
    }
}

void Server::slotDisconnectSocket()
{
    QTcpSocket *sender_socket = (QTcpSocket *)(sender());
    qDebug() << "MainWindow::slotDisconnectSocket socket" << sender_socket;
    qintptr sender_descriptor = sender_socket->socketDescriptor();

    qDebug() << sender_descriptor;

    int sockets_size = m_sockets.size();
    for(int i=0; i<sockets_size; ++i){
        QTcpSocket *socket = m_sockets.at(i);
        qDebug() << i << socket->socketDescriptor();
        if((socket->socketDescriptor() == sender_descriptor) ){
            m_sockets.removeAt(i);
            return;
        }

    }

}
